package com.sugon.controller.device;

import cn.afterturn.easypoi.entity.vo.TemplateExcelConstants;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelXorHtmlUtil;
import cn.afterturn.easypoi.excel.entity.ExcelToHtmlParams;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.afterturn.easypoi.view.PoiBaseView;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.annotation.AutoLog;
import com.sugon.annotation.DataFilter;
import com.sugon.annotation.NonBusinessParamValid;
import com.sugon.dao.DevAmPlanDao;
import com.sugon.dao.DevPlanRuleAmDao;
import com.sugon.entity.DevAmPlanEntity;
import com.sugon.entity.DevAmRulesEntity;
import com.sugon.entity.DevPlanRuleAmEntity;
import com.sugon.entity.SysMsgEntity;
import com.sugon.entity.vo.PlanRuleMapParam;
import com.sugon.modules.base.model.vo.BaseApproveParamVO;
import com.sugon.modules.base.model.vo.ProcessProgressConst;
import com.sugon.modules.device.service.IDeviceAmPlanManager;
import com.sugon.service.*;
import com.sugon.utils.PageUtils;
import com.sugon.utils.ProcessInfoEnum;
import com.sugon.utils.Query;
import com.sugon.utils.R;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 设备自主维护计划Controller
 *
 * @author YuXD
 * @date 2023-01-23
 */
@Controller
@RequestMapping("devAmPlan")
public class DevAmPlanController {

    @Autowired
    private DevAmPlanDao devAmMaintenancePlanDao;
    @Autowired
    private DevAmPlanService devAmMaintenancePlanService;
    @Autowired
    private IDeviceAmPlanManager devAmPlanManager;
    @Autowired
    private SysConfigService configService;
    @Autowired
    private DevAmPlanItemService devAmMaintenancePlanItemService;
    @Autowired
    private SysMsgService msgService;
    @Autowired
    private DevPlanRuleAmService devPlanRuleAmService;
    @Autowired
    private DevPlanRuleAmDao devPlanRuleAmDao;

    /**
     * 提交维护计划审核
     *
     * @param id
     * @return
     */
    @RequestMapping("/submitApprove/{id}")
    @ResponseBody
    public R submitApprove(@PathVariable("id") String id) {
        // 校验维护计划是否存在
        DevAmPlanEntity devMaintenancePlan = devAmMaintenancePlanService.queryObject(id);
        if (devMaintenancePlan == null) {
            return R.error("维护计划不存在，请确认！");
        }
        if (ProcessProgressConst.DEPT_APPROVING.equals(devMaintenancePlan.getStatus())) {
            return R.error("维护计划审核中，请耐心等待！");
        }
        if (ProcessProgressConst.PASSED.equals(devMaintenancePlan.getStatus())) {
            return R.error("维护计划已通过审核，请误重复提交！");
        }

        // 校验是否已添加规程
        boolean isExists = devAmMaintenancePlanItemService.isExists(id, null, null);
        if (!isExists) {
            return R.error("当前维护计划尚未添加设备维护项，请确认！");
        }
        devMaintenancePlan.setStatus(ProcessProgressConst.DEPT_APPROVING);
        boolean updateResult = devAmMaintenancePlanService.update(devMaintenancePlan) > 0;
        if (updateResult) {
            // 3、保存系统审批消息
            SysMsgEntity sysMsg = new SysMsgEntity();
            sysMsg.setDataId(devMaintenancePlan.getId());
            sysMsg.setDataUrl("../device/devplanmain.html?Id=" + sysMsg.getDataId());
            msgService.addApproveItem(ProcessInfoEnum.DEV_WHJH, sysMsg, 0);
        }
        return updateResult ? R.ok() : R.error();
    }

    /**
     * 自动调整设备维护计划
     *
     * @param id
     * @return
     */
    @RequestMapping("/autoAdjust/{id}")
    @ResponseBody
    public R autoAdjust(@PathVariable("id") String id) {
        // 校验维护计划是否存在
        DevAmPlanEntity devMaintenancePlan = devAmMaintenancePlanService.queryObject(id);
        if (devMaintenancePlan == null) {
            return R.error("维护计划不存在，请确认！");
        }
        // 只可以调整新增状态的设备维护计划
        if (!ProcessProgressConst.NEW.equals(devMaintenancePlan.getStatus())) {
            return R.error("维护计划审核中或已通过，不允许再次调整！");
        }
        // 校验是否已添加规程
        List<DevPlanRuleAmEntity> planRuleList = devPlanRuleAmDao.getByPlanId(id);
        if (CollectionUtil.isEmpty(planRuleList)) {
            return R.error("请先添加维护规程！");
        }
        // 校验是否已存在设备维护项
        boolean isExists = devAmMaintenancePlanItemService.isExists(id, null, null);
        if (!isExists) {
            return R.error("当前维护计划尚未添加设备维护项，请确认！");
        }
        return devAmPlanManager.autoAdjust(id) ? R.ok() : R.error("调整失败，请稍后重试！");
    }

    /**
     * 设备维护计划在线预览
     *
     * @param yearly 年度
     * @param list   维护计划ID字符串
     */
    @RequestMapping("/{action}")
    public void onlinePreview(@PathVariable("action") String action, String yearly, String list, ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws IOException {
        TemplateExportParams templateExportParams = new TemplateExportParams(configService.getPoiTemplatePath() + "devMaintenancePlanPreviewTemplate.xlsx");
        templateExportParams.setColForEach(true);
        // 获取设备维护计划预览模板数据
        Map<String, Object> devMaintenancePlanPreviewTemplateData = devAmPlanManager.generateDevMaintenancePlanPreviewTemplateData(yearly, list);
        if ("onlinePreview".equals(action)) {
            // 构建EXCEL
            Workbook workbook = ExcelExportUtil.exportExcel(templateExportParams, devMaintenancePlanPreviewTemplateData);
            // 生成HTML预览
            ExcelToHtmlParams excelToHtmlParams = new ExcelToHtmlParams(workbook);
            response.setHeader("Content-Type", "text/html;charset=utf-8");
            response.getOutputStream().write(ExcelXorHtmlUtil.excelToHtml(excelToHtmlParams).getBytes());
        } else {
            modelMap.put(TemplateExcelConstants.FILE_NAME, yearly + "年度设备维护计划");
            modelMap.put(TemplateExcelConstants.PARAMS, templateExportParams);
            modelMap.put(TemplateExcelConstants.MAP_DATA, devMaintenancePlanPreviewTemplateData);
            PoiBaseView.render(modelMap, request, response, TemplateExcelConstants.EASYPOI_TEMPLATE_EXCEL_VIEW);
        }
    }

    /**
     * 设备维护计划实施跟踪，展示
     */
    @RequestMapping("/follow")
    public void follow(@RequestParam("id") String id, HttpServletResponse response) throws IOException {
        TemplateExportParams templateExportParams = new TemplateExportParams(configService.getPoiTemplatePath() + "devMaintenancePlanImplementFollowTemplate.xlsx");
        templateExportParams.setColForEach(true);
        // 获取设备维护计划预览模板数据
        Map<String, Object> devMaintenancePlanPreviewTemplateData = devAmPlanManager.generatePlanImplementFollowTemplateData(id);
        // 构建EXCEL
        Workbook workbook = ExcelExportUtil.exportExcel(templateExportParams, devMaintenancePlanPreviewTemplateData);
        // 生成HTML预览
        ExcelToHtmlParams excelToHtmlParams = new ExcelToHtmlParams(workbook);
        response.setHeader("Content-Type", "text/html;charset=utf-8");
        response.getOutputStream().write(ExcelXorHtmlUtil.excelToHtml(excelToHtmlParams).getBytes());
    }

    @DataFilter(deptAlias = "WORKSHOP", userAlias = "MODIFY_USER")
    @RequestMapping("/list")
    @ResponseBody
    public R list(@RequestParam Map<String, Object> params) {
        //查询列表数据
        Query query = new Query(params);
        List<DevAmPlanEntity> devMaintenancePlanList = devAmMaintenancePlanService.queryList(query);
        int total = devAmMaintenancePlanService.queryTotal(query);
        PageUtils pageUtil = new PageUtils(devMaintenancePlanList, total, query.getLimit(), query.getPage());
        return R.ok().put("page", pageUtil);
    }

    @RequestMapping("/info/{id}")
    @ResponseBody
    public R info(@PathVariable("id") String id) {
        DevAmPlanEntity devMaintenancePlan = devAmMaintenancePlanService.queryObject(id);
        return R.ok().put("devPlanMain", devMaintenancePlan);
    }

    @RequestMapping("/listAllRelatedRule")
    @ResponseBody
    public R listByEnd(@RequestParam Map<String, Object> params) {
        // 检查参数中是否含有计划ID,如果有找到设备
        String planId = MapUtil.getStr(params, "planId");
        if (StrUtil.isEmpty(planId)) {
            return R.error("设备维护计划必选！");
        }
        // 校验设备维护计划是否存在
        DevAmPlanEntity devMaintenancePlan = devAmMaintenancePlanService.queryObject(planId);
        if (devMaintenancePlan == null) {
            return R.error("设备维护计划不存在，请确认！");
        }
        Query query = new Query(params);
        List<DevAmRulesEntity> devMaintenPlanList = devPlanRuleAmService.queryRelatedRuleList(query);
        int total = devPlanRuleAmService.queryRelatedRuleTotal(query);
        PageUtils pageUtil = new PageUtils(devMaintenPlanList, total, query.getLimit(), query.getPage());
        return R.ok().put("page", pageUtil);
    }

    @NonBusinessParamValid
    @AutoLog("设备维护计划--保存")
    @RequestMapping("/save")
    @ResponseBody
    public R save(@Validated @RequestBody DevAmPlanEntity devMaintenancePlan, BindingResult bindingResult) {
        R x = validDevMaintenancePlanParam(devMaintenancePlan);
        if (x != null) {
            return x;
        }
        return devAmMaintenancePlanService.save(devMaintenancePlan) > 0 ? R.ok() : R.error();
    }

    @NonBusinessParamValid
    @AutoLog("设备维护计划--删除关联规程")
    @RequestMapping("/deleteRule")
    @ResponseBody
    public R deleteRule(@Validated @RequestBody PlanRuleMapParam planRuleMapParam, BindingResult bindingResult) {
        // 校验设备维护计划是否存在
        DevAmPlanEntity devMaintenancePlan = devAmMaintenancePlanService.queryObject(planRuleMapParam.getPlanId());
        if (devMaintenancePlan == null) {
            return R.error("设备维护计划不存在，请确认！");
        }
        devAmPlanManager.deleteRule(planRuleMapParam.getPlanId(), planRuleMapParam.getRuleIds());
        return R.ok();
    }

    @NonBusinessParamValid
    @AutoLog("设备维护计划--修改")
    @RequestMapping("/update")
    @ResponseBody
    public R update(@RequestBody DevAmPlanEntity devMaintenancePlan) {
        R x = validDevMaintenancePlanParam(devMaintenancePlan);
        if (x != null) {
            return x;
        }
        // 校验维护计划是否存在
        DevAmPlanEntity devMaintenancePlanInDB = devAmMaintenancePlanService.queryObject(devMaintenancePlan.getId());
        if (devMaintenancePlanInDB == null) {
            return R.error("维护计划不存在，请确认！");
        }
        if (ProcessProgressConst.DEPT_APPROVING.equals(devMaintenancePlanInDB.getStatus())) {
            return R.error("维护计划审核中，不允许更改！");
        }
        if (ProcessProgressConst.PASSED.equals(devMaintenancePlanInDB.getStatus())) {
            return R.error("维护计划已通过审核，不允许更改！");
        }
        return devAmMaintenancePlanService.update(devMaintenancePlan) > 0 ? R.ok() : R.error();
    }

    @AutoLog("设备维护计划--删除")
    @RequestMapping("/delete")
    @RequiresPermissions("devAmPlan:delete")
    @ResponseBody
    public R delete(@RequestBody String[] ids) {
        devAmMaintenancePlanService.deleteBatch(ids);
        return R.ok();
    }

    @RequestMapping("/queryAll")
    @ResponseBody
    public R queryAll(@RequestParam Map<String, Object> params) {
        List<DevAmPlanEntity> list = devAmMaintenancePlanService.queryList(params);
        return R.ok().put("list", list);
    }

    @AutoLog("审核设备维护计划")
    @RequestMapping("/apply")
    @RequiresPermissions("devAmPlan:approve")
    @ResponseBody
    @NonBusinessParamValid
    public R apply(@Validated @RequestBody BaseApproveParamVO approveParam, BindingResult bindingResult) {
        approveParam.setProcessItem(ProcessInfoEnum.DEV_WHJH);
        return devAmPlanManager.workshopApprove(approveParam) ? R.ok() : R.error();
    }

    /**
     * 在新增或更新设备维护计划时，校验设备维护计划参数
     *
     * @param devMaintenancePlan
     * @return
     */
    private R validDevMaintenancePlanParam(@RequestBody DevAmPlanEntity devMaintenancePlan) {
        Date startDate = devMaintenancePlan.getStartDate();
        Date endDate = devMaintenancePlan.getEndDate();
        if (DateUtil.compare(startDate, endDate) >= 0) {
            return R.error("结束日期必须晚于开始日期！");
        }
        int yearly = DateUtil.year(startDate);
        if (yearly < DateUtil.thisYear()) {
            return R.error("计划年份不得晚于今年！");
        }
        if (yearly != DateUtil.year(endDate)) {
            return R.error("开始和结束日期必须是同一年份！");
        }
        int num = devAmMaintenancePlanDao.countLineSERangeRepeat(devMaintenancePlan.getId(), devMaintenancePlan.getDevLineId(), startDate, endDate);
        if (num > 0) {
            return R.error("同一产线维护计划起止日期不允许重合！");
        }
        devMaintenancePlan.setYearly(yearly);
        return null;
    }

}
